home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
keyb
/
stuft310.zip
/
STUFFIT.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-04-21
|
49KB
|
1,997 lines
PAGE 80,132
TITLE "StuffIt, Delayed keyboard stuffer. (C) Terje Mathisen 1989-91"
Version EQU 310h
VerStr EQU '3.10ß'
; LOCALS ; Use TASM features for easier development.
; NOJUMPS
TicksPrDay EQU 1573041
TicksPrHour EQU 65543
BIOS SEGMENT AT 40h
ORG 1Ah
BufferHead dw ?
BufferTail dw ?
BufferStart dw 16 dup (?)
BufferEnd LABEL word
ORG 49h
VideoMode db ?
CrtWidth dw ?
ORG 4Eh
CurrStart dw ?
Cursor dw ?
ORG 6Ch
BIOS_Timer dw 2 dup (?)
BIOS ENDS
BOOT SEGMENT AT 0F000h
ORG 0FFF0h
RebootLocation LABEL FAR
BOOT ENDS
; To reduce the resident size of StuffIt, the script is compressed into tokens
; using the following algorithm:
;
; 0 means that this is a character code which will be followed by a scan code
;
; 224 means the same as 0, (224 is lead-in code for the cursor keypad on the
; enhanced keyboard.)
;
; 254 is an escape character, followed by a char:scan pair. This is also used
; if we need to enter Chr(254) or Chr(255)
;
; 255 is the lead-in for an extended function code. It will be followed by
; one of these codes:
;
; Codes for extended functions, i.e not normal keys:
REBOOT_CODE = 0
ATTIME_CODE = 1
DELTATIME_CODE = 2
FIND_CODE = 3
PROMPT_CODE = 4
PRTSCRN_CODE = 5
BREAK_CODE = 6
; Use 255 to signal that the following is an extended function
EXTENDED_CODE = 255
; Use 254 as lead-in for keys that need both char & scan.
GETWORD_CODE = 254
; All other codes (1-221,223-253) are presumed to be single characters to
; place in the kbd buffer. All of them will receive the same scan code (2).
; If your application cannot accept this, you must use the {c} or [c] syntax,
; where <c> is any character. This will be translated to the US std enh kbd
; char:scan pair.
CODE SEGMENT PARA PUBLIC 'code'
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
ORG 0
PspStart label byte
ORG 5Ch
ResidentSize dw ?
;LowStart label byte
ORG 80h
CommandLen db ?
CommandLine LABEL BYTE
ORG 100h
start:
jmp init
Semafor equ 'ST' ; Short for STuffit
LowStart label byte
HighStart label byte
MoveDown EQU HighStart - LowStart ; Relocation factor for resident
; part of StuffIt
Int2F proc far
cmp ax,0E000h
je @@maybe
@@chain:
; jmp [OldInt2F]
db 0EAh
OldInt2F dd ?
@@maybe:
cmp dx,Semafor ; Be safe, insist on semafor in DX
jne @@chain
@@We_Are_Here:
mov al,0FFh
mov dx,cs
mov bx,Version
iret
Int2F endp
; Here comes the actual, INT 8, code, which will run on every timer tick to
; execute the tokenized script.
;
; To reduce the performance overhead of having StuffIt loaded, I use a dirty
; trick: Self-modifying code.
;
; When the script has finished, the total overhead is reduced to just
; 3 instructions: PUSHF / CALL (FAR IMMEDIATE) OldTimer / IRET
PUSH_AX_OPCODE EQU 50h ; Opcode for PUSH AX, used when active
IRET_OPCODE EQU 0CFh ; Opcode for IRET, used when disabled
MyTimer PROC FAR
pushf
; call [OldTimer] ; Call the old timer code first, to
db 09Ah ; do it's stuff and re-enable the HW.
OldTimer dw ?,?
SelfModify label byte ; This will be IRET when idle
push ax ; PUSH AX = 50h, IRET = 0CFh
; The [active] flag is initialized to -1. This way I can use an INC
; instruction to detect the first entry into this code. Multiple
; invocations will jump directly to the exit code, with very little
; overhead. (A total of only 7 instructions and 1 short jump.)
inc byte ptr [cs:active-MoveDown] ; INC from -1 to 0
jnz Already_Active
STI
CLD
push bx
push cx
push dx
push si
push di
push ds
push es
push cs
pop ds
ASSUME DS:CODE
mov es,[BiosSeg-MoveDown] ; I store 40h in a memory variable and
; load ES from it, as this saves one
; instruction vs MOV AX,40/MOV ES,AX
ASSUME ES:BIOS
call word ptr [StuffMode-MoveDown] ; State machine, call the current
; state handler.
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
CLI
Already_Active:
dec byte ptr [cs:active-MoveDown]
pop ax
iret
MyTimer ENDP
ASSUME CS:CODE,DS:CODE,ES:BIOS
StuffFinished:
mov [SelfModify-MoveDown],IRET_OPCODE ; Disable by self-modifying
; May be re-enabled by a later
; invocation of StuffIt.
ret
NextKey proc near
mov si,[StuffPtr-MoveDown]
GetNext:
cmp si,[StuffEnd-MoveDown]
jae StuffFinished
lodsb
cmp al,GETWORD_CODE
ja Extended ; Extended function
je @@GetBoth ; 254 => char, scan follows
mov ah,2 ; Simulate scan = 2 for normal chars
cmp al,224 ; Character for Enh.Kbd new keys
je @@GetScan
or al,al
jne stuff
@@GetScan:
mov ah,[si]
inc si
jmp short stuff
@@GetBoth:
lodsw
Stuff:
CLI
mov di,[BufferTail]
stos word ptr [BIOS:di]
cmp di, OFFSET BufferEnd
jb @@1
mov di, OFFSET BufferStart
@@1:
cmp di,[BufferHead]
je @@Overflow
mov [BufferTail],di
STI
StuffOK:
mov [StuffPtr-MoveDown],si
jmp GetNext
@@OverFlow:
STI
ret
NextKey ENDP
ExtendedTable label word
dw Reboot - MoveDown
dw AbsTime - MoveDown
dw DeltaTime - MoveDown
dw StartFind - MoveDown
dw StartPrompt - MoveDown
dw PrtScrn - MoveDown
dw CtrlBreak - MoveDown
NrOfCodes = ($ - offset ExtendedTable) SHR 1
Extended PROC near
lodsb ; Get function code!
cmp al,NrOfCodes
jae StuffFinished ; Program Error! Abort the script!
cbw ; All codes are <= 127, so CBW is OK!
mov bx,ax
shl bx,1
jmp ExtendedTable[bx - MoveDown] ; Jump to function handler
Extended endp
Reboot proc near
mov word ptr [BIOS: 72h],1234h ; == Warm Boot (CtrlAltDel)
jmp RebootLocation ; == F000:FFF0
Reboot endp
PrtScrn proc near
int 5
jmp GetNext
PrtScrn endp
CtrlBreak proc near
int 1Bh
xor ax,ax
jmp Stuff
CtrlBreak endp
AbsTime: ; Both Abs time & Delta time land here
DeltaTime: ; ---- " ----
GetTime proc near
cmp al, DELTATIME_CODE
lodsw ; Next 3 bytes is # of ticks
mov dl,[si]
jz @@TimeOk ; Delta time, so wait # of ticks
; Wait until time equal: Calculate remaining ticks
sub ax,[Bios_Timer]
sbb dl,BYTE PTR [Bios_Timer+2]
jae @@TimeOk
add ax,TicksPrDay AND 0FFFFh
adc dl,TicksPrDay Shr 16
@@TimeOK:
inc si
mov [StuffPtr-MoveDown],si ; Point to next byte
sub dh,dh ; Fill top of DX with 0
or ax,dx
jz @@WaitZero ; Special case, wait for empty kbd
mov [CountLow-MoveDown],ax
mov [